package com.cykj.pos.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Base64Utils;
import org.springframework.util.ObjectUtils;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

public class XinlongSignUtil {
    private  Logger logger = LoggerFactory.getLogger(XinlongSignUtil.class);

    public final static String ALGO_AES_CBC_NoPadding = "AES/CBC/NoPadding";
    public final static String ALGO_AES_CBC_PKCS5Padding = "AES/CBC/PKCS5Padding";
    public final static String ALGO_AES_ECB_NoPadding = "AES/ECB/NoPadding";
    public final static String ALGO_AES_ECB_PKCS5Padding = "AES/ECB/PKCS5Padding";
    private  String appkey;

    private  String appsecret;
    private  String traceID;
    private  String companyid;
    private  String mainAccount;
    private  String version;
    //签约回调地址
    private  String notify_url;
    //签约完成重定向地址
    private  String redirect_url;
    //提现回调地址
    private  String tx_notify_url;
    private String timep;
    public XinlongSignUtil(String saasAppkey, String saasAppsecret,String version,String traceID,String companyid,String mainAccount,String redirect_url,String notify_url,String tx_notify_url){
        appkey = saasAppkey;
        appsecret = saasAppsecret;
        this.version=version;
        this.traceID=traceID;
        this.companyid=companyid;
        this.mainAccount=mainAccount;
        this.notify_url=notify_url;
        this.redirect_url=redirect_url;
        this.tx_notify_url=tx_notify_url;
    }
    public  String getAppkey() {
        return appkey;
    }

    public  String getAppsecret() {
        return appsecret;
    }

    public  String getVersion(){ return version;}
    public  String getNotifyUrl(){ return notify_url;}
    public  String getRedirectUrl(){ return redirect_url;}


    /**
     * 获取签名
     * @return
     */
    public  String getsSignature(){
        Map<String, Object> params = new HashMap<>();
        long timp=System.currentTimeMillis();
        System.out.println(timp);
        this.timep=timp+"";
        params.put("timestamp",timp);
        params.put("appKey",getAppkey());
        params.put("version",getVersion());
        params.put("appSecret",getAppsecret());
        /** 对加密前的字符串进行sha1 加密 */
        String signString = buildSignString(params);
        logger.info("薪龙渠道生成签名字符串明文：{}",signString);
        /** 对加密前的字符串进行sha1 加密 */
        signString = DigestUtils.sha1Hex(signString).toUpperCase();
        logger.info("薪龙渠道生成签名字符串sha1加密后：{}",signString);
        /** 转成16 进制编码，并转为大写字符串 */
        //signString = str2HexStr(signString).toUpperCase();
        logger.info("薪龙渠道生成签名字符串密文：{}",signString);

        return signString;
    }

    /**
     * 获取业务参数
     * @param data
     * @return
     * @throws NoSuchPaddingException
     * @throws NoSuchAlgorithmException
     * @throws InvalidAlgorithmParameterException
     * @throws InvalidKeyException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     */
    public  String getRequestBody(Map<String,Object> data) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        JSONObject jsonObject=new JSONObject();
        for (String key :data.keySet()) {
            jsonObject.put(key,data.get(key));
        }
        String key = getAppsecret();
        String ivString = key;
        //偏移量
        byte[] iv = ivString.getBytes();
        logger.info("加密前数据：【{}】",data);
        Cipher cipher = Cipher.getInstance(ALGO_AES_CBC_NoPadding);
        int blockSize = cipher.getBlockSize();
        byte[] dataBytes = jsonObject.toString().getBytes();
        int length = dataBytes.length;
        //计算需要填充长度
        if(length % blockSize != 0){
            length = length + (blockSize - (length % blockSize));
        }
        byte[] plaintext = new byte[length];
        //填充补位数据
        System.arraycopy(dataBytes,0,plaintext,0,dataBytes.length);
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(),"AES");
        //设置偏移量参数
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.ENCRYPT_MODE,keySpec,ivSpec);
        byte[] encryped = cipher.doFinal(plaintext);
        String encrypedStrr = Base64.encode(encryped);
        logger.info("加密后数据：【{}】",encrypedStrr);
        return encrypedStrr;
    }

    /**
     * 请求体解码
     * @param requestBody
     * @return
     * @throws NoSuchPaddingException
     * @throws NoSuchAlgorithmException
     * @throws InvalidAlgorithmParameterException
     * @throws InvalidKeyException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     */
    public JSONObject deRequestBody(String requestBody) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {

        String key = getAppsecret();
        String ivString = key;
        //偏移量
        byte[] iv = ivString.getBytes();

        SecretKeySpec skey = new SecretKeySpec(key.getBytes(), "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(ivString.getBytes(), 0, iv.length);
        Cipher cipher = Cipher.getInstance(ALGO_AES_CBC_NoPadding);
        cipher.init(Cipher.DECRYPT_MODE, skey, ivSpec);// 初始化
        byte[] result = cipher.doFinal(new Base64().decode(requestBody));
        System.out.println(new String(result));
        JSONObject jsonObject=JSONObject.parseObject(new String(result));
        System.out.println(jsonObject.toJSONString());
        return jsonObject;
    }
    /**
     * 构建签名字符串
     * 将所有参与签名字段按照参数名的字典顺序排序
     * 以参数1 值1 参数2 值2 参数...的顺序拼接，（列如a=1&c=3&b=2 变为a1b2c3））
     * 开发者密钥以appSecret=***按第一步规则拼接到排序字符串中（列如a1b2c3 则变为appSecret***a1b2c3）
     * 按key+排序后的参数+secret,得到加密前字符串
     * @return String
     */
    public  String buildSignString(Map<String, Object> params) {
        if (params == null || params.size() == 0) {
            return "";
        }
        List<String> keys = new ArrayList<>(params.size());

        for (String key : params.keySet()) {
            if (ObjectUtils.isEmpty(params.get(key)))
                continue;
            keys.add(key);
        }
        /*key按照a-z排序**/
        Collections.sort(keys);

        /*key+排序后的参数+secret**/
        StringBuilder buf = new StringBuilder("key");
        /*构建排序后的参数**/
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key).toString();
            /*拼接非空字段**/
            if(StringUtils.isNotBlank(value)) {
                buf.append(key + value);
            }
        }
        buf.append("secret");

        return buf.toString();
    }

    /**
     * 链接薪龙
     * @param sign
     * @param requestBody
     * @return
     */
    public JSONObject submit(String service,String sign, String requestBody) {
        String url="https://xlapi.51xinlong.com/ws-test/rute?service="+service;
        Map<String, String> data = new HashMap<String, String>();
        data.put("timestamp",this.timep);
        data.put("appKey",getAppkey());
        data.put("signature",sign);
        data.put("version",getVersion());
        data.put("requestBody",requestBody);
        String result = doPost(this, url, new Gson().toJson(data));
        System.out.println("返回:" + result);
        JSONObject jsonObject =JSONObject.parseObject(result);
        return jsonObject;
    }


    //发送json请求
    public static String doPost(XinlongSignUtil xinlongSignUtil, String url, String data) {
        //创建httpClient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String result = "";
        try {
            //创建http请求
            HttpPost httpPost = new HttpPost(url);

            httpPost.addHeader("Content-Type", "application/json;charset=utf-8");
            httpPost.addHeader("Authorization","Bearer "+ xinlongSignUtil.getToken());
            httpPost.addHeader("traceID", xinlongSignUtil.traceID);
            httpPost.addHeader("companyid", xinlongSignUtil.companyid);
            httpPost.addHeader("mainAccount", xinlongSignUtil.mainAccount);
            //创建请求内容
            String jsonStr = data;
            StringEntity entity = new StringEntity(jsonStr, "utf-8");
            httpPost.setEntity(entity);
            response = httpClient.execute(httpPost);
            result = EntityUtils.toString(response.getEntity(), "utf-8");
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            if (response != null) {
                try {
                    response.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
            if (httpClient != null) {
                try {
                    httpClient.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }
        return result;
    }

    public String getToken(){
        //创建httpClient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String result = "";
        try {
            //创建http请求
            HttpPost httpPost = new HttpPost("https://xlapi.51xinlong.com/ws-test/auth/openapi");
            httpPost.addHeader("Content-Type", "application/json;charset=utf-8");
            Map<String, String> data = new HashMap<String, String>();
            data.put("appid",getAppkey());
            data.put("secret",getAppsecret());
            //创建请求内容
            String jsonStr = new Gson().toJson(data);
            StringEntity entity = new StringEntity(jsonStr, "utf-8");
            httpPost.setEntity(entity);
            response = httpClient.execute(httpPost);
            result = EntityUtils.toString(response.getEntity(), "utf-8");
            JSONObject jsonObject=JSONObject.parseObject(result);
            String token=jsonObject.getString("access_token");
            if(StringUtils.isNotBlank(token)){
                result=token;
            }
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            if (response != null) {
                try {
                    response.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
            if (httpClient != null) {
                try {
                    httpClient.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }
        return result;
    }
    /**
     * 加密
     * @param original
     * @param
     * @return
     */
    public  String encrypt(String original) throws Exception{
        byte[] enc = AESUtil.encrypt(AESUtil.ALGO_AES_CBC_NoPadding, getAppsecret().getBytes(), getAppsecret().getBytes(), Base64Utils.encode(original.getBytes()));//original.getBytes(SaasConstant.CHARSET_UTF8));
        return new String(enc);
    }

    /**
     * 解密
     * @param encMessage
     * @return
     * @throws Exception
     */
    public  String decrypt(String encMessage) throws Exception {
        byte[] dec = AESUtil.decrypt(AESUtil.ALGO_AES_CBC_NoPadding, getAppsecret().getBytes(), getAppsecret().getBytes(), encMessage.getBytes("UTF-8"));
        return new String(dec, "UTF-8");
    }

    public static void main(String[] args) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
        XinlongSignUtil xl=new XinlongSignUtil("402764463259168768",
                "QXAaaMETWCpaC3cP",
                "V1.1.0","402764636353904641",
                "402764605378965504",
                "323331000007777","www.baidu.com",
                "http://mxm.vaiwan.com/pose/receiver/callBack",
                "http://mxm.vaiwan.com/pose/receiver-tx/callBack");
//        //创建签约用户
//        Map<String,Object> data =new HashMap<String ,Object>();
//        data.put("mobile","15611363356");
//        data.put("idNumber","220122198812262544");
//        data.put("realname","mxm");
//        String sign=xl.getsSignature();
//        String requestBody=xl.getRequestBody(data);
//        JSONObject submitCreateUser=xl.submit("submitCreateUser",sign,requestBody);
//        String accountId="";
//        if(submitCreateUser.getString("code").equals("0000")){
//            accountId=submitCreateUser.getJSONObject("data").getString("accountId");
//        }
//        System.out.println(accountId);
//        //电子签约
//        Map<String,Object> data1=new HashMap<String,Object>();
//        data1.put("accountId",accountId);//创建签约用户是返回的accountId
//        data1.put("notify_url",xl.getNotifyUrl());
//        data1.put("redirect_url",xl.getRedirectUrl());
//        String signqy=xl.getsSignature();
//        String requestBodyqy=xl.getRequestBody(data1);
//        JSONObject submitSign=xl.submit("submitSign",signqy,requestBodyqy);
//        String url="";
//        String longUrl="";
//        if(submitSign.getString("code").equals("0000")){
//            url=submitSign.getJSONObject("data").getString("url");
//            longUrl=submitSign.getJSONObject("data").getString("longUrl");
//        }
//        System.out.println(url);
//        System.out.println(longUrl);
////        调取风控
//        Map<String,Object> data2=new HashMap<String,Object>();
//        data2.put("natchno","MXM12345678901");
//        data2.put("uid",xl.traceID);//账号中UID
//        data2.put("idcard","220122198812262515");
//        data2.put("idtypename","1");
//        data2.put("inAcctName","mxm");
//        data2.put("inAcctNo","123123123");
//        data2.put("ccyCode","OTHERBANK");
//        data2.put("cardType","DC");
//        data2.put("tranAmount","1");
//        data2.put("cardAttribute","C");
//        data2.put("mobile","15611363385");
//        String sign=xl.getsSignature();
//        String requestBody=xl.getRequestBody(data2);
//        JSONObject getRiskControl=xl.submit("getRiskControl",sign,requestBody);//返回:{"code":"0000","message":"SUCCESS","data":{"pass":1,"description":"success"}}
////        单笔提现
//        Map<String,Object> data3=new HashMap<String,Object>();
//        data3.put("uid",xl.traceID);
//        JSONArray jsarr=new JSONArray();
//        JSONObject dis=new JSONObject();
//        dis.put("natchno","MXM12345678901");//
//        dis.put("outerInstNatchno","MXM12345678901");
//        dis.put("idtypename","1");
//        dis.put("idcard","220122198812262515");
//        dis.put("mobile","15611363385");
//        dis.put("ccyCode","OTHERBANK");
//        dis.put("tranAmount",1);
//        dis.put("inBankName","阿萨德");
//        dis.put("inAcctNo","6228480538250792974");
//        dis.put("inAcctName","mxm");
//        dis.put("cardType","DC");
//        dis.put("cardAttribute","C");
//        dis.put("bankName","AD");
//        jsarr.add(dis);
//        System.out.println("-----------------------------"+jsarr.toJSONString());
//        data3.put("distributionlist",jsarr);
//        data3.put("notify_url",xl.tx_notify_url);
//        String signtx=xl.getsSignature();
//        String requestBodytx=xl.getRequestBody(data3);
//        JSONObject submitGrantDetail=xl.submit("submitGrantDetail",signtx,requestBodytx);
        //回调解码
//        String requestbody="SSaTZxWui7JW0Ldwz1ZSac0ODCYlE7brrpqu+AIlsZMUgd8bPmuXW70n3ewGB7Q3aUPRZrqC1TKAj9LBamxbTj0FS4BGf5kpHeALGVdpYTGtwtxLexFkSPzuSR9W+X+s0BxBKD3RLT42O04xXK9WN2UTE6cVBlMB2nvyxg5OJLjh8PlGmqBpQqhC4dHOeLWq6gXKEzPJ3QOuUoMy4qqMa5RjzcB1eMIEuqkpTm1ZGyXdWJCth1FBXhrIQKYtDr+6YIIdimGZyQ3oMrHbOPmf/j4G3W8lbKG51YilQEoA5cU=";
//        xl.deRequestBody(requestbody);
    }

}
